package concurrency.prod_cons.moniteur;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MoniteurProdCons {

	// Variables internes
	private final String[] tampon;
	private final int MAX_MESSAGE;
	private int tete;
	private int queue;
	private int nbMessage;

	private final Lock lock = new ReentrantLock();
	private final Condition condVIDE = lock.newCondition();
	private final Condition condPLEIN = lock.newCondition();

	// private final Object condPLEIN = new Object();
	// private final Object condVIDE = new Object();

	private Object moniteur = new Object();

	// Points d'entree
	public void deposer(String message) {
		lock.lock();
		try {
			while (nbMessage == MAX_MESSAGE) {
				try {
					condVIDE.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			tampon[queue] = message + " [" + queue + "] --->";
			queue = (queue + 1) % MAX_MESSAGE;
			nbMessage++;
			condPLEIN.signal();
		} finally {
			lock.unlock();
		}
	}

	public String retirer() {
		String message = null;
		lock.lock();
		try {
			while (nbMessage == 0) {
				try {
					condPLEIN.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			message = tampon[tete];
			message += "|<--- [" + tete + "]";
			tete = (tete + 1) % MAX_MESSAGE;
			nbMessage--;
			condVIDE.signal();
			return message;
		} finally {
			lock.unlock();
		}
	}

	// Initialisations
	public MoniteurProdCons(int tailleTampon) {
		tampon = new String[tailleTampon];
		tete = 0;
		queue = 0;
		nbMessage = 0;
		MAX_MESSAGE = tailleTampon;
	}
}
